package com.ld.shieldsb.common.web;

import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;

import com.ld.shieldsb.common.core.model.PropertiesModel;
import com.ld.shieldsb.common.core.util.StackTraceUtil;
import com.ld.shieldsb.common.core.util.StringUtils;
import com.ld.shieldsb.dao.BasicDao;
import com.ld.shieldsb.dao.MySqlBaseDao;
import com.ld.shieldsb.dao.OracleBaseDao;
import com.ld.shieldsb.db.model.DB;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class DaoFactory {
    private static final Map<String, BasicDao> DAOS_MAP = new HashMap<>();
    private static final Map<String, Class<? extends BasicDao>> DAO_CLASS_MAP = new HashMap<>(); // 类对象map，key为不同数据库的key

    static {
        // 注意需要在调用前加入，DAO类要求有(String key)的构造函数
        DAO_CLASS_MAP.put(DB.MYSQL, MySqlBaseDao.class);
        DAO_CLASS_MAP.put(DB.ORACLE, OracleBaseDao.class);
    }

    // 其他需要注册的类，可以在具体项目中注册，注意需要在调用前加入
    public static void registerDAOClass(String key, Class<? extends BasicDao> clses) {
        DAO_CLASS_MAP.put(key, clses);
    }

    /**
     * 
     * 获取dao
     * 
     * @Title getDao
     * @author 吕凯
     * @date 2018年2月3日 上午11:08:52
     * @param key
     *            db前缀
     * @return DynamicBaseDao
     */
    public static BasicDao getDao(String key) {
        BasicDao dao = DAOS_MAP.get(key);
        if (StringUtils.isNotBlank(key) && dao == null) {
            synchronized (DAOS_MAP) {
                String dbUrl = PropertiesModel.CONFIG.getString(key + "url");
                if (StringUtils.isNotEmpty(dbUrl)) {
//                    getDAOInstance(key, dbUrl);
                    dao = DAOS_MAP.get(key);
                    if (dao == null) {
                        dao = getDAOInstance(key, dbUrl);
                        if (dao != null) {
                            DAOS_MAP.put(key, dao);
                        } else {
                            log.warn("前缀为：" + key + "的数据库初始化失败！" + StackTraceUtil.getTrace());
                        }
                    }
                } else {
                    log.warn("前缀为：" + key + "的数据库url未定义！" + StackTraceUtil.getTrace());
                }
            }
        }
        return dao;
    }

    /**
     * 获取DAO实例
     * 
     * @Title getDAOInstance
     * @author 吕凯
     * @date 2019年3月12日 下午3:20:37
     * @param key
     * @param dbUrl
     * @return BasicDao
     */
    @SuppressWarnings("rawtypes")
    private static BasicDao getDAOInstance(String key, String dbUrl) {
        BasicDao dao = null;
        if (StringUtils.isNotBlank(dbUrl)) {
            String dbType = DB.getDBType(dbUrl);
            Class<? extends BasicDao> daoClass = DAO_CLASS_MAP.get(dbType);
            if (daoClass == null) {
                log.warn("前缀为：" + key + "，dbUrl为" + dbUrl + "的数据库DAO类未注册！");
            } else {
                Constructor con;
                // 通过构造器对象 newInstance 方法对对象进行初始化 有参数构造函数
                try {
                    con = daoClass.getConstructor(String.class);
                    dao = (BasicDao) con.newInstance(key);
                } catch (Exception e) {
                    log.error("", e);
                }
            }
        }
        return dao;
    }

    /**
     * 移除dao
     * 
     * @Title removeDao
     * @author 吕凯
     * @date 2018年2月3日 下午12:35:05
     * @param key
     * @return DynamicBaseDao
     */
    public static boolean removeDao(String key) {
        BasicDao dao = DAOS_MAP.get(key);
        if (dao != null) {
            // 删除
            DAOS_MAP.remove(key);
        }
        return true;
    }

    /**
     * 清空所有dao
     * 
     * @Title clear
     * @author 吕凯
     * @date 2018年2月24日 上午9:07:57 void
     */
    public static void clear() {
        synchronized (DAOS_MAP) {
            DAOS_MAP.clear();
        }
    }

}
